package com.cheetah.service.impl;

import com.cheetah.dto.UserDTO;
import com.cheetah.entity.User;
import com.cheetah.exceptions.CheetahRuntimeException;
import com.cheetah.mapper.UserMapper;
import com.cheetah.service.UserService;
import com.cheetah.utils.JsonUtil;
import com.cheetah.utils.MapStructMapper;
import com.cheetah.utils.UUIDUtil;
import com.cheetah.vo.RegisterUserVO;
import com.cheetah.vo.UserVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.*;

import static com.cheetah.constants.KeyConstants.USERS_INFO;
import static com.cheetah.exceptions.UserError.*;

/**
 * @Author Administrator
 * @Date 2019/10/8
 * @Version V1.0
 * @Description:
 **/
@Service
public class UserServiceImpl implements UserService {

    public static final String SALT = "Xdxikxji";

    static final String MD5_PREFIX = "$1$";

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private MapStructMapper mapstructMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private JsonUtil jsonUtil;

    @Override
    public UserDTO register(RegisterUserVO registerUserVO) {
        User user = userMapper.findByAccount(registerUserVO.getAccount());
        if(user != null){
            throw new CheetahRuntimeException(ERROR_CODE_200101);
        }
        userMapper.insert(user);
        UserDTO userDTO = mapstructMapper.user2userDto(user);
        return userDTO;
    }

    @Override
    public void auth(String account, String password) {
        User user = userMapper.findByAccount(account);
        if(user != null){
            throw new CheetahRuntimeException(ERROR_CODE_200102);
        }

        if(!StringUtils.equals(DigestUtils.md5DigestAsHex((password + SALT).getBytes()),user.getPassword())){
            throw new CheetahRuntimeException(ERROR_CODE_200102);
        }
    }

    @Override
    public UserDTO save(UserVO userVO){
        User user = mapstructMapper.userVO2user(userVO);
        user.setOpenId(UUIDUtil.id());
        String encryptPassword = DigestUtils.md5DigestAsHex((user.getPassword() + SALT).getBytes());
        user.setPassword(encryptPassword);
        userMapper.insert(user);
        return mapstructMapper.user2userDto(user);
    }

    @Override
    public UserDTO update(UserVO userVO){
        User user = mapstructMapper.userVO2user(userVO);
        userMapper.updateByPrimaryKey(user);

        return mapstructMapper.user2userDto(user);
    }

    @Override
    public int deleteById(String id){
        return userMapper.deleteByPrimaryKey(id);
    }


    @Override
    public List<UserDTO> findUserByIds(String ids){
        List<String> list = Arrays.asList(ids.split(","));

        if(list.size() > 500){
            throw new CheetahRuntimeException(ERROR_CODE_200207);
        }

        List<String> usersCacheStr = redisTemplate.opsForHash().multiGet(USERS_INFO,list);

        List<User> users = new ArrayList<>();
        List<String> idsInCache = new ArrayList<>();
        usersCacheStr.forEach(s -> {
            users.add(jsonUtil.toObject(s,User.class));
        });

        if(idsInCache.size() > 0){
            list.removeAll(idsInCache);
            List<User> usersNotInCache = userMapper.selectByIds(StringUtils.join(list.toArray(),","));
            Map<String,String> usersMap = new HashMap<>();
            usersNotInCache.forEach(u -> {
                usersMap.put(String.valueOf(u.getId()),jsonUtil.toJsonStr(u));
            });
            redisTemplate.opsForHash().putAll(USERS_INFO,usersMap);
            users.addAll(usersNotInCache);
        }
        return  mapstructMapper.userListToUseDTOList(users);
    }
}

